package com.hoe.tsb;


import com.hoe.tsb.fraft.exception.FRaftException;
import lombok.Data;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * <p>
 * TBS配置类
 * </p>
 *
 *  TODO 配置写到代码里的，可以移到配置文件里
 *
 * @author hoe
 * @since 2022/11/21
 */
@Data
public class Configuration {

    //>>>>>>>>>>>>>>>>>>>>> FRaft 配置 <<<<<<<<<<<<<<<<<<<<<<<<<<<
    /**
     * Heartbeat频率（单位毫秒）
     */
    private Integer hfc = 40000;
    /**
     * 自动转为candidate超时时长（单位毫秒）<br/>
     * 至少不能少于30秒！！！
     */
    private Integer timeout = 60000;
    /**
     * 区块生成的周期（单位毫秒）
     */
//    private Integer blockGenInterval = 900000;
    private Integer blockGenInterval = 30000;
    /**
     * 区块生成的门限数量（单位个）
     */
    private Integer blockGenThreshold = 1000;
    /**
     * 默认使用UDP数据交换器
     */
    private String exchanger = "udp";
    /**
     * ACK回复的超时时长（单位毫秒）<br/>
     * 每隔这么长时间就会对没收到ACK的消息进行重传
     */
    private Integer ackTimeout = 10000;
    /**
     * 防止重复消费的集合最大容量
     */
    private Integer repeatListCapacity = 500;
    /*
{
	{
		"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgk7U4pRiRziLHItDOVUi+FzMuAfMX11tJSlZChA0y2HmgCgYIKoZIzj0DAQehRANCAASMcg7K5YuPZuIKpRC19rbjwCHhqCt/hMQvWZ20rZde4jDSo4ZWRK26xaAIbd0aAGaz2OOoQi2mMnom8MSzuM/L",
		"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjHIOyuWLj2biCqUQtfa248Ah4agrf4TEL1mdtK2XXuIw0qOGVkStusWgCG3dGgBms9jjqEItpjJ6JvDEs7jPyw=="
	},
	{
		"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgSRsw544+xmHfMnQbU327pFe4LXRq7r9I9b23ldOIm/ugCgYIKoZIzj0DAQehRANCAARgR9REfl6iyVoZ3bthz27dcI9LYEqyz4qGuHqwODFRbBMJABJlvE2oD/FkFwC5jEe1UNfbFiYIfdn65S2HB3tF",
		"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYEfURH5eoslaGd27Yc9u3XCPS2BKss+Khrh6sDgxUWwTCQASZbxNqA/xZBcAuYxHtVDX2xYmCH3Z+uUthwd7RQ=="
	},
	{
		"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgszVtPmRu+vt6M8xioSNUKSbtMw8TfYMsPWGwbV36JcugCgYIKoZIzj0DAQehRANCAAQVqkBQbyG9FNgS/6WLfsucOVYcnELG+0CvJzG4QVahZ6ARq3WVXv+lNxtLgBVivhq1pi5kCwc9Ewx2fDfLrhdn",
		"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFapAUG8hvRTYEv+li37LnDlWHJxCxvtArycxuEFWoWegEat1lV7/pTcbS4AVYr4ataYuZAsHPRMMdnw3y64XZw=="
	},
	{
		"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQglvtP1aP9G94ytNC2+UYq+QxL1OgOi0nlVCq4VIYAqyWgCgYIKoZIzj0DAQehRANCAATsIW7CcR2Pt4MYdj6diLF3KywPSYSId2tYfYCCjzIQZYaftJyuqhA1BBq0k269Wt6OENlT27WEGNok9nuhWeKp",
		"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7CFuwnEdj7eDGHY+nYixdyssD0mEiHdrWH2Ago8yEGWGn7ScrqoQNQQatJNuvVrejhDZU9u1hBjaJPZ7oVniqQ=="
	},
	{
		"MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgHYBr7TnR1QH+xAhShml21/k8EMB5SzK6ZRvOrRIP7+GgCgYIKoZIzj0DAQehRANCAASI14c5hQWPKsTUIYobZS/kddVDMHMis2l6B1jS+8zj7DzM6Jc5Ao5wx2g+N7IXwglI34xhOO0cyCvjYM8GYwXX",
		"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiNeHOYUFjyrE1CGKG2Uv5HXVQzBzIrNpegdY0vvM4+w8zOiXOQKOcMdoPjeyF8IJSN+MYTjtHMgr42DPBmMF1w=="
	}
}
     */
    /**
     * 当前节点信息
     */
    private Info current = new Info("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjHIOyuWLj2biCqUQtfa248Ah4agrf4TEL1mdtK2XXuIw0qOGVkStusWgCG3dGgBms9jjqEItpjJ6JvDEs7jPyw==");
    /**
     * 环签名私钥
     * TODO 实际使用时私钥应该存放在服务器安全目录，由服务端动态读取
     */
    private String ringPrivateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgk7U4pRiRziLHItDOVUi+FzMuAfMX11tJSlZChA0y2HmgCgYIKoZIzj0DAQehRANCAASMcg7K5YuPZuIKpRC19rbjwCHhqCt/hMQvWZ20rZde4jDSo4ZWRK26xaAIbd0aAGaz2OOoQi2mMnom8MSzuM/L";
//    /**
//     * 集群信息（不包含自身）<br/>
//     * 集群的总节点数等于cluster.length + 1，自身<br/>
//     * TODO 集群信息是预设的，这是基于溯源链的可信场景考虑，后续如果要扩展为动态节点，则需要扩展FRaft算法
//     */
////    private Info[] cluster = {
////            new Info(12151, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYEfURH5eoslaGd27Yc9u3XCPS2BKss+Khrh6sDgxUWwTCQASZbxNqA/xZBcAuYxHtVDX2xYmCH3Z+uUthwd7RQ=="),
////            new Info(12152, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFapAUG8hvRTYEv+li37LnDlWHJxCxvtArycxuEFWoWegEat1lV7/pTcbS4AVYr4ataYuZAsHPRMMdnw3y64XZw=="),
////            new Info(12153, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7CFuwnEdj7eDGHY+nYixdyssD0mEiHdrWH2Ago8yEGWGn7ScrqoQNQQatJNuvVrejhDZU9u1hBjaJPZ7oVniqQ=="),
////            new Info(12154, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiNeHOYUFjyrE1CGKG2Uv5HXVQzBzIrNpegdY0vvM4+w8zOiXOQKOcMdoPjeyF8IJSN+MYTjtHMgr42DPBmMF1w=="),
////    };
    /**
     * LevelDb的数据存放路径
     */
    private String levelDbDataPath = "D:\\Tool\\test\\levelDb.dat";

    private static Configuration defaultCfg = new Configuration();

    private Configuration() {
    }

    @Data
    public static class Info {
        /**
         * IP地址
         */
        private String ip;
        /**
         * 端口
         */
        private Integer port;
        /**
         * 环签名公钥
         */
        private String ringPublicKey;

        public Info(String ringPublicKey) {
            this(12150, ringPublicKey);
        }
        public Info(int port, String ringPublicKey) {
            this("127.0.0.1", port, ringPublicKey);
        }
        public Info(String ip, int port, String ringPublicKey) {
            this.ip = ip;
            this.port = port;
            this.ringPublicKey = ringPublicKey;
        }
    }

    public static ConfigBuilder builder() {
        return new ConfigBuilder();
    }

    public static class ConfigBuilder {
        Info info;
        Integer hfc;
        Integer timeout;
        Integer ackTimeout;
        Integer repeatListCapacity;
        String exchanger;
        String ringPrivateKey;
        String levelDbDataPath;

        public ConfigBuilder info(Info info) {
            this.info = info;
            return this;
        }

        public ConfigBuilder hfc(int hfc) {
            this.hfc = hfc;
            return this;
        }

        public ConfigBuilder timeout(int timeout) {
            this.timeout = timeout;
            return this;
        }

        public ConfigBuilder ackTimeout(int ackTimeout) {
            this.ackTimeout = ackTimeout;
            return this;
        }

        public ConfigBuilder repeatListCapacity(int repeatListCapacity) {
            this.repeatListCapacity = repeatListCapacity;
            return this;
        }

        public ConfigBuilder exchanger(String exchanger) {
            this.exchanger = exchanger;
            return this;
        }

        public ConfigBuilder ringPrivateKey(String ringPrivateKey) {
            this.ringPrivateKey = ringPrivateKey;
            return this;
        }

        public ConfigBuilder levelDbDataPath(String levelDbDataPath) {
            this.levelDbDataPath = levelDbDataPath;
            return this;
        }

        public Configuration build() {
            Configuration configuration = new Configuration();
            settleAllField(configuration);
            return configuration;
        }

        void settleAllField(Configuration configuration) {
            //这部分反射用法后续可以封装到单独的工具类中，或直接使用现成的反射工具类
            Field[] declaredFields = ConfigBuilder.class.getDeclaredFields();
            for (Field field : declaredFields) {
                //获取配置值
                Object fieldVal;
                try {
                    fieldVal = field.get(this);
                } catch (IllegalAccessException e) {
                    throw new FRaftException("初始化配置类错误", e);
                }

                if (fieldVal != null) {
                    char[] fieldName = field.getName().toCharArray();
                    fieldName[0] -= 32;
                    String setterMethodName = "set" + new String(fieldName);
                    //构建set方法
                    Method fieldSetter;
                    try {
                        fieldSetter = Configuration.class.getDeclaredMethod(setterMethodName, field.getType());
                        fieldSetter.invoke(configuration, fieldVal);
                    } catch (Exception e) {
                        throw new FRaftException("初始化配置类赋初值时错误", e);
                    }
                }
            }
        }

    }

    public static Configuration getDefault() {
        return defaultCfg;
    }

}
